<script setup lang="ts">
import { computed, reactive, ref, toRaw } from "vue";
import { onLoad, onUnload } from "@dcloudio/uni-app";
import {
  order_set_api,
  get_max_specs_api,
} from "@/package/mall/api/tour_product";
import { create_order_api } from "@/package/mall/api/tour_order";
import { items_api } from "@/package/mall/api/tour_info";
import { EV_CONTACTS } from "@/constant/event";
import { strReplaceByLen } from "@/utils/string";
import { Router } from "@/utils/router";
import { Toast } from "@/utils/toast";

import FormStepper from "@/components/form/stepper.vue";
import OrderTravelItem from "./components/order-travel-item.vue";
import OrderContactsItem from "./components/order-contacts-item.vue";
import FormWord from "@/components/form/word.vue";
import OrderSettleBar from "../goods/components/order-settle-bar.vue";
import PopupBottom from "@/components/popup/bottom.vue";
import PopupModal from "@/components/popup/modal.vue";

onLoad((options) => {
  infoData.product_name = decodeURIComponent(options?.product_name);
  infoData.use_date = options?.use_date;
  infoData.group_type = options?.group_type;
  infoData.specs_name = decodeURIComponent(options?.specs_name);
  infoData.price = options?.price;
  formData.specs_id = options?.id;

  getOrderSet().then(() => {
    specClick(infoData.min_buy_num);

    // 获取出行人
    reloadContactsList();
  });

  tempData.guiderId = options?.guiderId;

  uni.$on(EV_CONTACTS, contactsCallback);
});
onUnload(() => uni.$off(EV_CONTACTS, contactsCallback));

const getOrderSet = () => {
  return order_set_api({
    specs_id: formData.specs_id,
    use_date: infoData.use_date,
  }).then((resp) => {
    infoData.person_num = resp.person_num;
    infoData.min_buy_num = resp.min_buy_num;
    infoData.max_buy_num =
      resp.is_limit_buy === 1 ? resp.max_buy_num : resp.stock;
    infoData.is_limit_buy = resp.is_limit_buy;
    contactsKeyList.value = resp.contacts_info;
    travelKeyList.value = resp.tourist_info;
    tempData.tourist_info_type = resp.tourist_info_type;
    tempData.product_reserve = resp.product_reserve;
    tempData.horizontal_pic = resp.horizontal_pic;
  });
};

const payPrice = computed(() => {
  // 订单总金额 = type：1：拼团，单价 * 数量；2：私家团，单价
  return (
    Number(infoData.price) *
    (infoData.group_type === "1" ? formData.order_num : 1)
  ).toFixed(2);
});

const infoData = reactive({
  product_name: "",
  use_date: "",
  group_type: "1",
  specs_name: "",
  price: "",
  person_num: 1,
  min_buy_num: 1,
  max_buy_num: 1,
  is_limit_buy: 0,
  order_num2: 0,
  specs_name2: "",
  travel_num: 1,
});

const formData = reactive({
  specs_id: "",
  order_num: 1,
  buyer_name: "",
  buyer_phone: "",
  desc: "",
});

const specClick = (n: number) => {
  const fn = (n: number) => {
    formData.order_num = n;
    infoData.travel_num =
      tempData.tourist_info_type === 1
        ? 1
        : tempData.tourist_info_type === 2
        ? n * infoData.person_num
        : 0;
    // 当前已选出行人大于购买份数，刷新出行人
    if (travelCheckList.value.length > infoData.travel_num) {
      travelCheckList.value.splice(
        infoData.travel_num,
        travelCheckList.value.length - infoData.travel_num
      );
    }
  };
  fn(n);
  // 私家团超过最大人数，切换套餐
  if (infoData.group_type === "1" || n <= infoData.max_buy_num) return;
  get_max_specs_api({
    specs_id: formData.specs_id,
    use_date: infoData.use_date,
    count: n,
  }).then((resp) => {
    if (resp) {
      infoData.order_num2 = n;
      infoData.specs_name2 = resp.name;
      popupModal.value?.show(
        {},
        () => {
          formData.specs_id = resp.id;
          infoData.specs_name = resp.name;
          infoData.price = resp.price;
          getOrderSet();
        },
        () => fn(infoData.max_buy_num) // 不切换，返回原来人数
      );
    } else {
      // 没有套餐，返回原来人数
      fn(infoData.max_buy_num);
      Toast.show("已达套餐最大人数");
    }
  });
};

const contactsKeyList = ref<string[]>([]);
const contactsClick = () => {
  Router.navigateTo(`/package/my/pages/contacts/list?mode=select&type=1`);
};

const travelKeyList = ref<string[]>([]);
const travelCheckList = ref<string[]>([]);
const travelCheckNum = computed(() => {
  return contactsList.value.filter((i, d) => {
    return d > 2 && travelCheckList.value.includes(i.id);
  }).length;
});
const travelList = computed(() => {
  return contactsList.value.filter((i) => {
    return travelCheckList.value.includes(i.id);
  });
});
const travelContactsClick = (id: string) => {
  const _travelCheckList = travelCheckList.value;
  const index = _travelCheckList.indexOf(id);
  // 点击已选择，直接取消
  if (index !== -1) {
    _travelCheckList.splice(index, 1);
  } else if (infoData.travel_num === 1) {
    // 最大可选；1：替换；
    _travelCheckList.splice(0, 1, id);
  } else {
    // 已选最大
    _travelCheckList.length === infoData.travel_num
      ? Toast.show(`仅需填写${infoData.travel_num}位出行人信息`)
      : _travelCheckList.push(id);
  }
};
const travelAddClick = () => {
  const _contactsList = toRaw(contactsList.value);
  _contactsList.length <= 3
    ? Router.navigateTo(`/package/my/pages/contacts/edit`)
    : Router.navigateTo(
        `/package/my/pages/contacts/list?mode=select&type=2&num=${
          infoData.travel_num
        }&id=${travelList.value.map((i) => i.id).join(",")}`
      );
};
const travelDelClick = (index: number) => {
  travelCheckList.value.splice(index, 1);
};
const travelEditClick = (id: string) => {
  Router.navigateTo(`/package/my/pages/contacts/edit?id=${id}`);
};

const tipClick = () => {
  Router.navigateTo(tempData.product_reserve);
};
const detailVisible = ref(false);

const createClick = (type: "detail") => {
  if (type === "detail") {
    detailVisible.value = !detailVisible.value;
  } else {
    Toast.showLoading();
    create_order_api({
      ...toRaw(formData),
      use_date: infoData.use_date,
      price: payPrice.value,
      tourist_info: toRaw(travelList.value),
      guider_id: tempData.guiderId,
    })
      .then((resp) => {
        Toast.hideLoading();
        Router.navigateTo(
          `/package/mall/pages/jps/settle?${Router.dataToQuery({
            id: resp.pre_order_id,
            horizontal_pic: tempData.horizontal_pic,
            product_name: infoData.product_name,
            specs_name: infoData.specs_name,
            price: infoData.price, // 套餐单价
            group_type: infoData.group_type, // 拼团类型
            order_num: formData.order_num, // 购买数量；私家团时为出行人数
          })}`
        );
      })
      .catch(() => Toast.hideLoading());
  }
};

const contactsList = ref<any[]>([]);
const reloadContactsList = () => {
  return items_api().then((resp) => {
    contactsList.value = resp.items.map((i) => {
      return {
        ...i,
        cardNo_str:
          i.cardNo.length > 10 ? strReplaceByLen(i.cardNo, 6) : i.cardNo,
      };
    });
  });
};

const contactsCallback = (e: {
  type: "select" | "edit" | "del";
  data: any;
}) => {
  console.info(`触发事件：${EV_CONTACTS}`, e);
  if (e.type === "select") {
    if (e.data.type === "1") {
      const contacts = e.data.data[0];
      formData.buyer_name = contacts.name;
      formData.buyer_phone = contacts.phone;
    } else {
      travelCheckList.value = e.data.data.map((i: any) => i.id);
    }
  } else {
    reloadContactsList().then(() => {
      // 更新当前已选出行人
      travelCheckList.value = travelCheckList.value.filter((i) => {
        return contactsList.value.some((j) => i === j.id);
      });
    });
  }
};

const popupModal = ref<InstanceType<typeof PopupModal>>();
const tempData = {
  tourist_info_type: 1, // 出行人必填类型，1：必填1人；2：必填全部；3：不需填写
  product_reserve: "",
  horizontal_pic: "",
  guiderId: "",
};
</script>

<template>
  <view class="order-bg"></view>

  <view class="order-info">
    <view class="order-info-name">{{ infoData.product_name }}</view>
    <view class="order-info-spec">出行日期：{{ infoData.use_date }}</view>
    <view class="order-info-spec">已选：{{ infoData.specs_name }}</view>
  </view>

  <view class="order-spec">
    <view class="order-spec-item">
      <view class="order-spec-lable">价格</view>

      <view class="order-spec-price">
        <view class="order-spec-price2">￥</view>
        {{ infoData.price }}
        <view class="order-spec-price3">
          /{{ infoData.group_type === "1" ? "位" : "团" }}
        </view>
      </view>
    </view>
    <view class="order-spec-item">
      <view class="order-spec-lable">
        {{ infoData.group_type === "1" ? "购买人数" : "出行人数" }}
      </view>

      <view class="order-spec-tip" v-if="infoData.group_type === '2'">
        （请如实填写，必填）
      </view>
      <view class="order-spec-limit" v-else-if="infoData.is_limit_buy === 1">
        <image
          class="order-spec-limit2"
          src="/package/mall/static/jps-order-limit.png"
        />
        最大限购{{ infoData.max_buy_num }}份
      </view>

      <view class="order-spec-num">
        <FormStepper
          :modelValue="formData.order_num"
          :min="infoData.min_buy_num"
          :max="infoData.group_type === '1' ? infoData.max_buy_num : 9999"
          :step="infoData.person_num"
          @update:modelValue="specClick"
        />
      </view>
    </view>
  </view>

  <view class="order-contacts">
    <view class="order-contacts-title">
      联系人信息<span class="order-contacts-tip">（必填）</span>
    </view>
    <view class="order-contacts-form">
      <view
        class="order-contacts-item"
        v-if="contactsKeyList.includes('buyer_name')"
      >
        <view class="order-contacts-lable">姓名</view>
        <input
          class="order-contacts-input"
          v-model="formData.buyer_name"
          placeholder="填写联系人姓名"
        />
        <view class="order-contacts-btn" @click="contactsClick">选择</view>
      </view>
      <view
        class="order-contacts-item"
        v-if="contactsKeyList.includes('buyer_phone')"
      >
        <view class="order-contacts-lable">手机号码</view>
        <input
          class="order-contacts-input"
          v-model="formData.buyer_phone"
          type="tel"
          placeholder="用于联系与接收确认短信"
        />
      </view>
    </view>
  </view>

  <view class="order-travel" v-if="infoData.travel_num > 0">
    <view class="order-travel-title">
      需填
      <span style="color: #ff4d42">&nbsp;{{ infoData.travel_num }}&nbsp;</span>
      位出行人
    </view>
    <view class="order-travel-tip">
      以下信息用于购买门票，为保证顺利入园，请确保出行人信息与证件号一致
    </view>
    <view class="order-travel-menu">
      <template v-for="(i, d) of contactsList" :key="i.id">
        <view
          class="order-travel-menu2"
          v-if="d < 3"
          @click="travelContactsClick(i.id)"
        >
          <OrderTravelItem
            :modelValue="travelCheckList.includes(i.id)"
            :text="i.name"
          />
        </view>
      </template>
      <view class="order-travel-menu3" @click="travelAddClick">
        {{ contactsList.length > 3 ? "选择/新增" : "新增+" }}
        <view class="order-travel-menu4" v-if="travelCheckNum > 0">
          {{ travelCheckNum }}
        </view>
      </view>
    </view>
    <view class="order-travel-data">
      <view class="order-travel-item" v-for="(i, d) of travelList" :key="i.id">
        <image
          class="order-travel-del"
          src="@/package/mall/static/jps-order-close.png"
          @click="travelDelClick(d)"
        />
        <view style="flex-grow: 1; min-width: 0">
          <OrderContactsItem
            :index="d + 1"
            :keyList="travelKeyList"
            :info="i"
          />
        </view>
        <image
          class="order-travel-edit"
          src="@/package/mall/static/jps-order-edit.png"
          @click="travelEditClick(i.id)"
        />
      </view>
    </view>
  </view>

  <view class="order-remark">
    <view class="order-remark-title">留言备注</view>
    <FormWord :modelValue="formData.desc.length" :maxlength="100">
      <textarea
        class="order-remark-input"
        v-model="formData.desc"
        auto-height
        placeholder="如您有更多需求，请留言告诉我们"
      />
    </FormWord>
  </view>

  <view class="order-tip">
    点击去支付即代表您已阅读并同意
    <view class="order-tip-link" @click="tipClick">产品预定须知</view>
  </view>

  <PopupBottom v-model="detailVisible" title="费用明细" :zIndex="8">
    <view class="order-detail">
      <view class="order-detail-name">{{ infoData.product_name }}</view>

      <view class="order-detail-item">
        <view class="order-detail-spec">已选：{{ infoData.specs_name }}</view>
        <view style="flex-shrink: 0">
          <view class="order-detail-price">
            ￥{{ infoData.price }}/{{
              infoData.group_type === "1" ? "位" : "团"
            }}
          </view>
          <view class="order-detail-num" v-if="infoData.group_type === '1'">
            x{{ formData.order_num }}
          </view>
        </view>
      </view>
    </view>
  </PopupBottom>
  <view class="order-fixed">
    <OrderSettleBar
      title="合计"
      :price="payPrice"
      detailVisible
      btnText="去结算"
      @btn-click="createClick"
    />
  </view>

  <PopupModal ref="popupModal">
    <view class="order-modal">
      当前套餐最大可选人数为<text style="color: #ff7900"
        >{{ infoData.max_buy_num }}人</text
      >。您选择的人数为<text style="color: #ff7900"
        >{{ formData.order_num2 }}人</text
      >，已超过当前套餐最大可选人数。是否需要切换到<text style="color: #ff7900"
        >“{{ infoData.specs_name2 }}”</text
      >套餐？
    </view>
  </PopupModal>
</template>

<style lang="scss">
page {
  padding-top: 30rpx;
  padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
}

.order-bg {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  height: 348rpx;
  background: linear-gradient(
    180deg,
    #fa8831,
    #fa8831 52%,
    rgba(255, 255, 255, 0)
  );
}

.order-info {
  position: relative;
  padding: 30rpx;
  margin: 0 30rpx 20rpx;
  border-radius: 20rpx;
  background-color: #ffffff;

  .order-info-name {
    margin-bottom: 20rpx;
    font-size: 30rpx;
    color: #2d2d2d;
    line-height: 48rpx;
    font-weight: bold;
  }

  .order-info-spec {
    margin-top: 10rpx;
    font-size: 24rpx;
    color: #666666;
    line-height: 44rpx;
  }
}

.order-spec {
  position: relative;
  padding: 20rpx 20rpx 10rpx;
  margin: 0 30rpx 20rpx;
  border-radius: 20rpx;
  background-color: #ffffff;

  .order-spec-item {
    display: flex;
    align-items: center;
    margin-bottom: 20rpx;
  }

  .order-spec-lable {
    flex-shrink: 0;
    font-size: 28rpx;
    color: #333333;
    line-height: 42rpx;
    font-weight: bold;
  }

  .order-spec-price {
    display: flex;
    align-items: flex-end;
    margin-left: auto;
    font-size: 48rpx;
    color: #ee5734;
    line-height: 66rpx;
    font-weight: bold;
  }

  .order-spec-price2 {
    font-size: 36rpx;
    line-height: 58rpx;
  }

  .order-spec-price3 {
    margin-left: 4rpx;
    font-size: 26rpx;
    color: #666666;
    line-height: 58rpx;
    font-weight: 400;
  }

  .order-spec-tip {
    font-size: 24rpx;
    color: #666666;
  }

  .order-spec-limit {
    display: flex;
    align-items: center;
    height: 46rpx;
    padding: 0 8rpx;
    margin-left: 20rpx;
    font-size: 26rpx;
    color: #1bb942;
    border-radius: 4rpx;
    background-color: #f3fff6;
  }

  .order-spec-limit2 {
    width: 24rpx;
    height: 24rpx;
    margin-right: 6rpx;
  }

  .order-spec-num {
    flex-shrink: 0;
    margin-left: auto;
  }
}

.order-contacts {
  position: relative;
  padding: 30rpx 20rpx 20rpx;
  margin: 0 30rpx 20rpx;
  border-radius: 20rpx;
  background-color: #ffffff;

  .order-contacts-title {
    margin-bottom: 20rpx;
    font-size: 32rpx;
    color: #333333;
    line-height: 44rpx;
    font-weight: bold;
  }

  .order-contacts-tip {
    font-size: 24rpx;
    color: #666666;
    font-weight: 400;
  }

  .order-contacts-item {
    display: flex;
    align-items: center;
    height: 100rpx;
  }

  .order-contacts-lable,
  .order-contacts-input {
    font-size: 28rpx;
    color: #646566;
  }

  .order-contacts-lable {
    flex-shrink: 0;
    width: 130rpx;
  }

  .order-contacts-input {
    flex-grow: 1;
    min-width: 0;
    color: #2d2d2d;
  }

  .order-contacts-btn {
    flex-shrink: 0;
    width: 100rpx;
    margin-left: 20rpx;
    font-size: 24rpx;
    color: #999999;
    line-height: 50rpx;
    text-align: center;
    border-radius: 28rpx;
    background-color: #f9f9f9;
  }
}

.order-travel {
  padding: 30rpx 20rpx 20rpx;
  margin: 0 30rpx 20rpx;
  border-radius: 20rpx;
  background-color: #ffffff;

  .order-travel-title {
    margin-bottom: 20rpx;
    font-size: 32rpx;
    color: #333333;
    line-height: 44rpx;
    font-weight: bold;
  }

  .order-travel-tip {
    margin-bottom: 30rpx;
    font-size: 24rpx;
    color: #666666;
    line-height: 42rpx;
  }

  .order-travel-menu {
    display: flex;
    align-items: center;
    margin-bottom: 30rpx;
  }

  .order-travel-menu2,
  .order-travel-menu3 {
    width: 25%;
  }

  .order-travel-menu2 {
    margin-right: 10rpx;
  }

  .order-travel-menu3 {
    position: relative;
    font-size: 24rpx;
    color: #ff7900;
    line-height: 80rpx;
    text-align: center;
    border-radius: 10rpx;
    border: 2rpx solid #eeeeee;
  }

  .order-travel-menu4 {
    position: absolute;
    top: -14rpx;
    right: -12rpx;
    padding: 0 6rpx;
    font-size: 22rpx;
    color: #ffffff;
    line-height: 28rpx;
    font-weight: bold;
    border-radius: 50%;
    background-color: #f22f2f;
  }

  .order-travel-item {
    display: flex;
    align-items: center;
    padding: 20rpx 0;
  }

  .order-travel-del {
    flex-shrink: 0;
    align-self: flex-start;
    width: 28rpx;
    height: 28rpx;
    margin-top: 12rpx;
    margin-right: 12rpx;
  }

  .order-travel-edit {
    flex-shrink: 0;
    width: 34rpx;
    height: 34rpx;
    margin-left: 20rpx;
    margin-right: 10rpx;
  }
}

.order-remark {
  padding: 30rpx 20rpx 40rpx;
  margin: 0 30rpx 60rpx;
  border-radius: 20rpx;
  background-color: #ffffff;

  .order-remark-title {
    margin-bottom: 30rpx;
    font-size: 32rpx;
    color: #333333;
    line-height: 44rpx;
    font-weight: bold;
  }

  .order-remark-input {
    display: block;
    width: 100%;
    min-height: 256rpx;
    padding: 30rpx;
    font-size: 28rpx;
    color: #333333;
    border-radius: 20rpx;
    background-color: #f9f9f9;
    box-sizing: border-box;
  }
}

.order-tip {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 40rpx;
  font-size: 24rpx;
  color: #999999;
  line-height: 36rpx;

  .order-tip-link {
    color: #ffa300;
    text-decoration: underline;
  }
}

.order-fixed {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  height: 104rpx;
  padding-top: 16rpx;
  padding-bottom: env(safe-area-inset-bottom);
  background-color: #ffffff;
  z-index: 8;
}

.order-detail {
  padding-top: 20rpx;
  border-bottom: 122rpx solid #eeeeee;

  .order-detail-name {
    margin: 0 30rpx 20rpx;
    font-size: 30rpx;
    color: #333333;
    line-height: 44rpx;
  }

  .order-detail-item {
    display: flex;
    align-items: center;
    padding: 0 30rpx;
    margin-bottom: 10rpx;
  }

  .order-detail-spec {
    flex-grow: 1;
    min-width: 0;
    margin-right: 10rpx;
    font-size: 24rpx;
    color: #666666;
    line-height: 44rpx;
  }

  .order-detail-price {
    margin-bottom: 8rpx;
    font-size: 26rpx;
    color: #666666;
    line-height: 36rpx;
  }

  .order-detail-num {
    font-size: 24rpx;
    color: #666666;
    line-height: 32rpx;
    text-align: right;
  }
}

.order-modal {
  padding-left: 40rpx;
  padding-right: 40rpx;
  padding-bottom: 60rpx;
  text-align: center;
}
</style>